#if !defined(AFX_RENDERVIEWPORT_H__323772B6_5A57_4867_B973_A9102FE3001B__INCLUDED_)
#define AFX_RENDERVIEWPORT_H__323772B6_5A57_4867_B973_A9102FE3001B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// RenderViewport.h : header file
//

#include <Cry_Camera.h>
#include "Viewport.h"
#include "Objects\DisplayContext.h"

#include "Util/PredefinedAspectRatios.h"

// forward declarations.
class CBaseObject;
struct IPhysicalEntity;
typedef IPhysicalEntity * PIPhysicalEntity;

/////////////////////////////////////////////////////////////////////////////
// CRenderViewport window

class SANDBOX_API CRenderViewport : public CViewport, public IEditorNotifyListener
{
	DECLARE_DYNCREATE(CRenderViewport)
	// Construction

public:

	struct SResolution
	{
		SResolution() :
		width(0), height(0)
		{
		}

		SResolution(int w, int h) :
		width(w), height(h)
		{
		}

		int width;
		int height;
	};


public:
	CRenderViewport();

	/** Get type of this viewport.
	*/
	virtual EViewportType GetType() const { return ET_ViewportCamera; }
	virtual void SetType( EViewportType type ) { assert(type == ET_ViewportCamera); };

	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CRenderViewport)
	//}}AFX_VIRTUAL

	// Implementation
public:
	virtual ~CRenderViewport();
	void InitCommon();

	void OnPaintSafe();
	virtual void Update();

	virtual void OnTitleMenu( CMenu &menu );
	virtual void OnTitleMenuCommand( int id );

	void SetCamera( const CCamera &camera );
	const CCamera& GetCamera() const { return m_Camera; };
	virtual void SetViewTM( const Matrix34 &tm )
	{ SetViewTM(tm, false); }

	//! Map world space position to viewport position.
	virtual CPoint	WorldToView( Vec3 wp );
	virtual Vec3    WorldToView3D( Vec3 wp,int nFlags=0 );

	//! Map viewport position to world space position.
	virtual Vec3		ViewToWorld( CPoint vp,bool *collideWithTerrain=0,bool onlyTerrain=false, bool bSkipVegetation=false, bool bTestRenderMesh = false );
	virtual void		ViewToWorldRay( CPoint vp,Vec3 &raySrc,Vec3 &rayDir );
	virtual Vec3		ViewToWorldNormal( CPoint vp, bool onlyTerrain, bool bTestRenderMesh = false );
	virtual float		GetScreenScaleFactor( const Vec3 &worldPoint );
	virtual float GetAspectRatio() const;
	virtual void DrawTextLabel( DisplayContext &dc,const Vec3& pos,float size,const ColorF& color,const char *text, const bool bCenter=false );
	virtual bool HitTest( CPoint point,HitContext &hitInfo );
	virtual bool IsBoundsVisible( const AABB &box ) const;
	virtual void CenterOnSelection();

	void SetDefaultCamera();
	void SetSequenceCamera();
	void SetSelectedCamera();
	void SetCameraObject( CBaseObject *cameraObject );
	// This switches the active camera to the next one in the list of (default, all custom cams).
	void CycleCamera();

	void SetUniformScaling(f32 us) { m_fUniformScaling=us; };
  float GetUniformScaling() { return m_fUniformScaling; };
	void SetPlayerControl(uint32 i) { m_PlayerControl=i; };
	uint32 GetPlayerControl() { return m_PlayerControl; };

	const DisplayContext& GetDisplayContext() const	{	return m_displayContext;	}

	void SetPlayerPos(const Vec3& pos) 
	{ 
		m_AverageFrameTime=0.14f;

		m_AnimatedCharacter.SetIdentity();
		m_PhysEntityLocation.SetIdentity();

		m_EntityMat.SetIdentity();
		m_PrevEntityMat.SetIdentity();

		m_vSmoothEntityPosition	= Vec3(0,0,0);
		m_vSmoothEntityCatchUpPos	= Vec3(0,0,0);
		m_vSmoothEntityDirection	= Vec3(0,1,0);

		m_fUniformScaling	=	1.0f; 
		m_absCameraHigh=2.0f; 
		m_absCameraPos=Vec3(0,3,2); 
		m_absCameraPosVP=Vec3(0,-3,1.5); 

		m_absCurrentSpeed=-1.0f;
		m_absCurrentSlope= 0.0f;

		m_absLookDirectionXY=Vec2(0,1);

		m_LookAt=Vec3(ZERO);
		m_LookAtRate=Vec3(ZERO);
		m_vCamPos=Vec3(ZERO);
		m_vCamPosRate=Vec3(ZERO);

		m_relCameraRotX=0;
		m_relCameraRotZ=0;



		uint32 numSample6 = m_arrAnimatedCharacterPath.size();
		for (uint32 i=0; i<numSample6; i++)
			m_arrAnimatedCharacterPath[i]=Vec3(ZERO);

		numSample6 = m_arrSmoothEntityPath.size();
		for (uint32 i=0; i<numSample6; i++)
			m_arrSmoothEntityPath[i]=Vec3(ZERO);

		uint32 numSample7 = m_arrRunStrafeSmoothing.size();
		for (uint32 i=0; i<numSample7; i++)
		{
			m_arrRunStrafeSmoothing[i]=0;
		}

		m_vWorldDesiredBodyDirection=Vec2(0,1);
		m_vWorldDesiredBodyDirectionSmooth		=Vec2(0,1);
		m_vWorldDesiredBodyDirectionSmoothRate=Vec2(0,1);

		m_vWorldDesiredBodyDirection2=Vec2(0,1);

		m_vWorldDesiredMoveDirection=Vec2(0,1);
		m_vWorldDesiredMoveDirectionSmooth		=Vec2(0,1);
		m_vWorldDesiredMoveDirectionSmoothRate=Vec2(0,1);
		m_vLocalDesiredMoveDirection=Vec2(0,1);
		m_vLocalDesiredMoveDirectionSmooth		=Vec2(0,1);
		m_vLocalDesiredMoveDirectionSmoothRate=Vec2(0,1);

		m_vWorldAimBodyDirection=Vec2(0,1);
		m_MoveDirRad=0;




		m_MoveSpeedMSec=5.0f;
		m_key_W=0; m_keyrcr_W=0;
		m_key_S=0; m_keyrcr_S=0;
		m_key_A=0; m_keyrcr_A=0;
		m_key_D=0; m_keyrcr_D=0;
		m_key_SPACE=0; m_keyrcr_SPACE=0;
		m_ControllMode=0;

		m_State=-1;
		m_Stance=1; //combat 

		m_udGround	=0.0f;			
		m_lrGround	=0.0f;			
		AABB aabb		= AABB(Vec3(-40.0f,-40.0f,-0.25f),Vec3(+40.0f,+40.0f,+0.0f));
		m_GroundOBB	=	OBB::CreateOBBfromAABB( Matrix33(IDENTITY),aabb );
		m_GroundOBBPos = Vec3(0,0,-0.01f);
	};


	void ToggleFullscreen();	
	void SetDockingPaneWndID( int nID )	{	m_DockingPaneID = nID;	}

	CCamera m_Camera;

protected:
	void SetViewTM( const Matrix34 &tm,bool bMoveOnly );

	virtual float GetCameraMoveSpeed() const;

	// Called to render stuff.
	virtual void OnRender();

	virtual void OnEditorNotifyEvent( EEditorNotifyEvent event );

	//! Get currently active camera object.
	CBaseObject* GetCameraObject() const;
	void ToggleCameraObject();
	bool GetCameraObjectState();

	void RenderTerrainGrid( float x1,float y1,float x2,float y2 );
	void RenderConstructionPlane();
	void RenderProceduralConstructionPlane();
	void RenderSnapMarker();
	void RenderCursorString();
	void RenderSnappingGrid();
	void ProcessKeys();

	void RenderAll();
	void DrawAxis();
	void DrawBackground();
	void InitDisplayContext();
	void SetCurrentContext();

	// Update the safe frame, safe action, safe title, and borders rectangles based on 
	// viewport size and target aspect ratio.
	void UpdateSafeFrame();

	// Draw safe frame, safe action, safe title rectangles and borders.
	void RenderSafeFrame();

	// Draw one of the safe frame rectangles with the desired color.
	void RenderSafeFrame( const CRect& frame, float r, float g, float b, float a );

	// Draw the selection rectangle.
	void RenderSelectionRectangle();

	virtual bool CreateRenderContext();
	virtual void DestroyRenderContext();

	void OnMenuCommandChangeAspectRatio( unsigned int commandId );

	bool AdjustObjectPosition(const ray_hit &hit, Vec3 &outNormal, Vec3& outPos);
	bool RayRenderMeshIntersection(IRenderMesh * pRenderMesh, const Vec3 & vInPos, const Vec3 & vInDir, Vec3 & vOutPos, Vec3 & vOutNormal);

	bool AddCameraMenuItems( CMenu& menu, int InitialID, bool bHasTopSeperator, CMenu& customCameraMenu );	
	void ResizeView( int width, int height );

	std::vector<CString> m_customResPreset;
	
	int m_DockingPaneID;
	CMenu m_CustomCameraMenu;

	//! Assigned renderer.
	IRenderer*	m_renderer;
	I3DEngine*	m_engine;
	bool m_bRenderContextCreated;
	bool m_bInRotateMode;
	bool m_bInMoveMode;
	bool m_bInOrbitMode;
	bool m_bInZoomMode;

	CPoint m_mousePos;

	float m_moveSpeed;
	Vec3 m_orbitTarget;

	//-------------------------------------------
	//---   player-control in CharEdit        ---
	//-------------------------------------------
	f32 m_MoveSpeedMSec;

	uint32 m_key_W,m_keyrcr_W;
	uint32 m_key_S,m_keyrcr_S;
	uint32 m_key_A,m_keyrcr_A;
	uint32 m_key_D,m_keyrcr_D;

	uint32 m_key_SPACE,m_keyrcr_SPACE;
	uint32 m_ControllMode;


	bool m_bFullscreenInWindow;

	int32 m_Stance; 
	int32 m_State;
	f32 m_AverageFrameTime;

	uint32 m_PlayerControl;

	f32 m_fUniformScaling;
	f32 m_absCameraHigh;
	Vec3 m_absCameraPos;
	Vec3 m_absCameraPosVP;

	f32  m_absCurrentSpeed;  //in meters per second
	f32  m_absCurrentSlope;  //in radiants

	Vec2 m_absLookDirectionXY;

	Vec3 m_LookAt;
	Vec3 m_LookAtRate;
	Vec3 m_vCamPos;
	Vec3 m_vCamPosRate;


	f32 m_relCameraRotX;
	f32 m_relCameraRotZ;

	QuatT m_PhysEntityLocation;
	QuatTS m_AnimatedCharacter;

	Matrix34 m_AnimatedCharacterMat;
	Matrix34 m_EntityMat;
	Matrix34 m_PrevEntityMat;

	Vec3 m_vSmoothEntityPosition;
	Vec3 m_vSmoothEntityCatchUpPos;
	Vec3 m_vSmoothEntityDirection;

	std::vector<Vec3> m_arrVerticesHF;
	std::vector<uint16> m_arrIndicesHF;

	std::vector<Vec3> m_arrAnimatedCharacterPath;
	std::vector<Vec3> m_arrSmoothEntityPath;
	std::vector<f32> m_arrRunStrafeSmoothing;

	Vec2 m_vWorldDesiredBodyDirection;
	Vec2 m_vWorldDesiredBodyDirectionSmooth;
	Vec2 m_vWorldDesiredBodyDirectionSmoothRate;

	Vec2 m_vWorldDesiredBodyDirection2;


	Vec2 m_vWorldDesiredMoveDirection;
	Vec2 m_vWorldDesiredMoveDirectionSmooth;
	Vec2 m_vWorldDesiredMoveDirectionSmoothRate;
	Vec2 m_vLocalDesiredMoveDirection;
	Vec2 m_vLocalDesiredMoveDirectionSmooth;
	Vec2 m_vLocalDesiredMoveDirectionSmoothRate;
	Vec2 m_vWorldAimBodyDirection;
	f32 m_MoveDirRad;



	f32 m_udGround;			
	f32 m_lrGround;			
	OBB m_GroundOBB;
	Vec3 m_GroundOBBPos;

	//-------------------------------------------


	// Render options.
	bool m_bDisplayLabels;
	bool m_bShowSafeFrame;
	bool m_bRenderStats;

	CSize m_viewSize;

	// Index of camera objects.
	mutable GUID m_cameraObjectId;
	bool m_bSequenceCamera;
	bool m_bUpdating;
	bool m_bLockCameraMovement;

	int m_nPresedKeyState;

	Matrix34 m_prevViewTM;
	CString m_prevViewName;


	DisplayContext m_displayContext;

	PIPhysicalEntity * m_pSkipEnts;
	int m_numSkipEnts;

	static HWND m_currentContextWnd;

	CRect m_safeFrame;
	CRect m_safeAction;
	CRect m_safeTitle;

	CPredefinedAspectRatios m_predefinedAspectRatios;

	CRenderViewport* m_pSecondViewport;

	std::vector< CRenderViewport::SResolution > m_ResolutionPresets;	

	// Generated message map functions
protected:

	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnPaint();
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg int  OnMouseActivate( CWnd* pDesktopWnd,	UINT nHitTest,UINT message );
	afx_msg void OnDestroy();

	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_RENDERVIEWPORT_H__323772B6_5A57_4867_B973_A9102FE3001B__INCLUDED_)
